﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace Game3D
{
    /// <summary>
    ///  Enumeration of available move directions 
    /// </summary>
    public enum GameMoveDirections
    {
        Left,
        Right,
        Down
    }

    [Serializable]
    public class GameControl
    {
        /// <summary>
        /// List of meshes available to display
        /// </summary>
        public List<GameMesh> Meshes
        {
            get;
            set;
        }

        /// <summary>
        /// Viewport3D reference to control with the GameControl class
        /// </summary>
        public Viewport3D Viewport3D
        {
            get;
            set;
        }

        public GameControl()
        {
            Meshes = new List<GameMesh>();
        }

        public GameControl(List<GameMesh> meshes) : this()
        {
            this.Meshes = meshes;
        }

        public GameControl(Viewport3D viewport3D) : this()
        {
            this.Viewport3D = viewport3D;
        }

        public GameControl(Viewport3D viewport3D, List<GameMesh> meshes) : this()
        {
            this.Viewport3D = viewport3D;
            this.Meshes = Meshes;
        }

        public void Test()
        {
            Meshes.Add(new GameMesh(Shape.S, 360));
            //Meshes[0].GeometryModel.Material = new DiffuseMaterial(Brushes.Orange);
            Viewport3D.Children.Add(Meshes[0]);
        }

        /// <summary>
        /// Returns the last inserted mesh (shouldn't depend on index but on property of GameMesh
        /// </summary>
        /// <returns></returns>
        private GameMesh GetPlayerMesh()
        {
            return Meshes[Meshes.Count - 1];
        }

        /// <summary>
        /// Move player's mesh towards the given direction
        /// </summary>
        /// <param name="direction">The direction where the player wants the block to move</param>
        public void Move(GameMoveDirections direction)
        {
            Point currentPosition = GetPlayerMesh().Position;

            #region Direction Interpretation
            switch (direction)
            {
                case GameMoveDirections.Left:
                    currentPosition.X--;
                    break;
                case GameMoveDirections.Right:
                    currentPosition.X++;
                    break;
                case GameMoveDirections.Down:
                    currentPosition.Y--;
                    break;
                default:
                    Console.WriteLine("Default");
                    break;
            }
            #endregion 

            GetPlayerMesh().Position = currentPosition;
        }

        /// <summary>
        /// Instantly pull down the player block and generate new block
        /// </summary>
        public void PullDown()
        {
            throw new System.NotImplementedException();
        }

        /// <summary>
        /// Rotate the player block
        /// </summary>
        public void Rotate()
        {
            if (GetPlayerMesh().RotationZ > 90)
            {
                GetPlayerMesh().RotationZ -= 90;
            }
            else
            {
                GetPlayerMesh().RotationZ = 360;
            }

            Console.WriteLine(GetPlayerMesh().RotationZ);
        }

        /// <summary>
        /// End of Game (maybe unecessary)
        /// </summary>
        public void End()
        {
            throw new System.NotImplementedException();
        }

        /// <summary>
        /// Generate a GameField around the play area
        /// </summary>
        /// <param name="width">Width of GameField</param>
        /// <param name="height">Height of GameField</param>
        public void GenerateGamefield(int width, int height)
        {
            Random rand = new Random();

            // Generate random color index
            int randomNumber = rand.Next(7);

            // Horizontal
            int currentListLength = Meshes.Count;

            for (int posX = 0; posX < width; posX++)
            {
                GameMesh newGameMeshBottom = new GameMesh(Shape.Single, 360);
                newGameMeshBottom.GeometryModel.Material = new DiffuseMaterial(GameShapeColors.ResolveColor(randomNumber));
                newGameMeshBottom.Position = new Point(posX, 0);

                GameMesh newGameMeshTop = new GameMesh(Shape.Single, 360);
                newGameMeshTop.GeometryModel.Material = new DiffuseMaterial(GameShapeColors.ResolveColor(randomNumber));
                newGameMeshTop.Position = new Point(posX, height - 1);

                Meshes.Add(newGameMeshTop);
                Meshes.Add(newGameMeshBottom);
            }

            for (int i = currentListLength; i < 2 * (currentListLength + width); i++)
            {
                Viewport3D.Children.Add(Meshes[i]);
            }


            // Vertical
            currentListLength = Meshes.Count;
            Console.WriteLine(Meshes.Count);

            for (int posY = 1; posY < height - 1; posY++)
            {
                GameMesh newGameMeshBottom = new GameMesh(Shape.Single, 360);
                newGameMeshBottom.GeometryModel.Material = new DiffuseMaterial(GameShapeColors.ResolveColor(randomNumber));
                newGameMeshBottom.Position = new Point(0, posY);

                GameMesh newGameMeshTop = new GameMesh(Shape.Single, 360);
                newGameMeshTop.GeometryModel.Material = new DiffuseMaterial(GameShapeColors.ResolveColor(randomNumber));
                newGameMeshTop.Position = new Point(width - 1, posY);

                Meshes.Add(newGameMeshTop);
                Meshes.Add(newGameMeshBottom);
            }

            Console.WriteLine(Meshes.Count);

            for (int i = currentListLength; i < currentListLength + 2 * (height - 2); i++)
            {
                Viewport3D.Children.Add(Meshes[i]);
            }
        }
    }
}
